package com.aps.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aps.entity.domain.order.ApsOrder;
import com.aps.entity.domain.order.OrderDish;
import com.aps.entity.domain.schedule.ScheduleConfig;
import com.aps.entity.dto.*;
import com.aps.entity.eunm.DishStatus;
import com.aps.entity.eunm.OrderChangeType;
import com.aps.entity.eunm.OrderStatus;
import com.aps.entity.eunm.TimeUnitType;
import com.aps.service.IApsOrderService;
import com.aps.service.IKdsService;
import com.aps.service.IOrderDishService;
import com.aps.service.IPriorityRuleService;
import com.aps.service.rep.ApsOrderRep;
import com.aps.service.rep.OrderDishRep;
import com.aps.util.DateUtil;
import com.aps.util.ScheduleComponent;

/**
 * @author liaoguangan
 * @description <订单服务实现类>
 * @date 2018/4/1 15:30
 */
@Service
public class ApsOrderServiceImpl implements IApsOrderService {

    @Autowired
    private ApsOrderRep apsOrderRep;

    @Autowired
    private OrderDishRep orderDishRep;

    @Autowired
    private ScheduleComponent scheduleComponent;

    @Autowired
    private IOrderDishService orderDishService;

    @Autowired
    private IKdsService kdsService;

    @Autowired
    private IPriorityRuleService priorityRuleService;

    /**
     * POS下单接口
     *
     * @param apsOrderReqDTO
     */
    @Override
    public void save(ApsOrderReqDTO apsOrderReqDTO) {

        ApsOrder order = apsOrderReqDTO.getOrder();
        List<OrderDish> dishes = apsOrderReqDTO.getDishes();

        order.setStatus(OrderStatus.UNSTART);
        order = apsOrderRep.save(order); //保存订单

        //保存订单菜品
        for (OrderDish dish : dishes) {
            dish.setOrderNum(order.getOrderNum());
            dish.setStatus(DishStatus.UNSTART);
        }
        orderDishRep.save(dishes);

        //添加到待排程缓存队列
        scheduleComponent.addSchedule(order.getOrderNum());
    }

    /**
     * 设置订单状态
     * @param orderNum
     */
    @Override
    public void setOrderStauts(String orderNum) {
        //查询订单相关的开始菜品数量
        Integer count = orderDishRep.countByOrderNumAndStatus(orderNum, DishStatus.START);
        ApsOrder apsOrder = apsOrderRep.findByOrderNum(orderNum);

        if (count > 0) {
            apsOrder.setStatus(OrderStatus.START);
        } else {
            apsOrder.setStatus(OrderStatus.UNSTART);
        }
    }

    /**
     * load未开始订单
     *
     * @return
     */
    @Override
    public List<ApsOrder> findUnScheduleOrders() {
        return apsOrderRep.findByStatusOrderByOrderTimeAsc(OrderStatus.UNSTART);
    }

    /**
     * 排程
     */
    @Override
    public void schedule() {
        //未开始订单
        List<ApsOrder> apsOrders = this.findUnScheduleOrders();

        //按优先级排序
        priorityRuleService.sort(apsOrders);

        //设置菜品RequestTime
        List<ApsOrderRtDTO> apsOrderRtDTOS = orderDishService.calculateRequestTime(apsOrders);

        //设置PromiseTime
        orderDishService.calculatePromiseTime(apsOrderRtDTOS);

        for (ApsOrderRtDTO apsOrderRtDTOS1 : apsOrderRtDTOS) {
            for (ApsOrderDishDbDTO apsOrderDishDbDTO : apsOrderRtDTOS1.getList()) {
                System.out.print("\r\n" + apsOrderDishDbDTO.getDish().getName() + " -- RT: "
                        + apsOrderDishDbDTO.getRequestTime() + " PT: "
                        + apsOrderDishDbDTO.getPromiseTime() + "\r\n");
            }
        }
        //下发KDS
        kdsService.schedule(new ScheduleKdsDTO());
    }

    /**
     * 是否排程
     *
     * @return
     */
    @Override
    public boolean readSchedule() {
        ScheduleConfig config = scheduleComponent.getConfig();

        if (null == config) {
            return false;
        }

        Date nextScheduleTime = null != scheduleComponent.getNextScheduleTime() ? scheduleComponent
                .getNextScheduleTime() : DateUtil.addTime(TimeUnitType.S, -10);
        Integer maxValue = null != config.getMaxValue() ? config.getMaxValue() : 0;

        Boolean rs = !scheduleComponent.getScheduling() && (new Date().after(nextScheduleTime)
                || scheduleComponent.getMaxValue() >= config.getMaxValue()
                || scheduleComponent.getScheduleSoon());

        nextScheduleTime = DateUtil.addTime(config.getIntervalUnit(),
                config.getIntervalTime().intValue());

        //设置下次排程日期
        scheduleComponent.setNextScheduleTime(nextScheduleTime);
        return rs;
    }

    /**
     * 订单变更
     *
     * @param orderChangeReqDTO
     */
    @Override
    public void change(OrderChangeReqDTO orderChangeReqDTO) {
        ApsOrderChangeDTO apsOrderChangeDTO = orderChangeReqDTO.getApsOrderChangeDTO();
        List<OrderDishChangeDTO> orderDishChangeDTOs = orderChangeReqDTO.getOrderDishChangeDTOs();

        ApsOrder apsOrder = apsOrderRep.findByOrderNum(apsOrderChangeDTO.getOrderNum());

        Boolean scheduleSoon = false;
        //是否解HOLD订单
        if (apsOrderChangeDTO.getInOrdUnhold()) {
            apsOrder.setIsOrdHold(false);
            scheduleSoon = true;
        }

        //是否换台
        if (apsOrderChangeDTO.getIsTblChg()) {
            apsOrder.setTableNum(apsOrderChangeDTO.getNewTblNo());

            //订单变更反馈KDS
            kdsService.change(new OrderChangeToKdsDTO(apsOrderChangeDTO.getOrderNum(),
                    OrderChangeType.TABLE.getCode(), apsOrderChangeDTO.getNewTblNo()));
        }

        for (OrderDishChangeDTO odcd : orderDishChangeDTOs) {
            OrderDish orderDish = orderDishRep.findByOrderNumAndDishNumAndDishSeq(
                    apsOrderChangeDTO.getOrderNum(), odcd.getDishNum(), odcd.getDishSeq());

            switch (odcd.getRePick()) {
                case UNHOLD: {
                    orderDish.setHoldSign(false);
                    orderDishRep.save(orderDish);
                    break;
                }
                case BACK: {
                    orderDishService.back(orderDish);
                    break;
                }
                case CHANGE: {
                    //先退菜
                    orderDish = orderDishRep.findByOrderNumAndDishSeq(
                            apsOrderChangeDTO.getOrderNum(), odcd.getRplcDishSeq());
                    orderDishService.back(orderDish);

                    //加菜
                    orderDishService.add(apsOrderChangeDTO.getOrderNum(), odcd, DishStatus.CHANGE);
                    break;
                }
                case ADD: {
                    orderDishService.add(apsOrderChangeDTO.getOrderNum(), odcd, DishStatus.ADD);
                    break;
                }
                default: {

                }
            }
        }

        if (orderDishChangeDTOs.size() > 0) {
            scheduleSoon = true;
        }

        apsOrderRep.save(apsOrder);

        //触发排程
        scheduleComponent.setScheduleSoon(scheduleSoon);
    }
}
